home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ARASAN_S.ZIP / NOTATION.CPP < prev    next >
C/C++ Source or Header  |  1994-08-07  |  5KB  |  240 lines

  1. // Copyright 1994 by Jon Dart.  All Rights Reserved.
  2.  
  3. #include "notation.h"
  4. #include "board.h"
  5. #include "emove.h"
  6. #include "bearing.h"
  7. #include <ctype.h>
  8. #include <string.h>
  9.  
  10. // This module handles I/O of standard algebraic notation (SAN).
  11. // Note that we can't put this into the Move class, because a
  12. // move doesn't contain enough info by itself to produce SAN -
  13. // we need the board position, too.
  14.  
  15. void Notation::
  16. Image(const Board & b, const Move & m, char *image)
  17. {
  18.    ExtendedMove emove(b, m);
  19.    Piece p = emove.PieceMoved();
  20.  
  21.    if (emove.Special() == ExtendedMove::KCastle)
  22.    {
  23.      strcpy(image, "O-O");
  24.      return;
  25.    }
  26.    else if (emove.Special() == ExtendedMove::QCastle)
  27.    {
  28.      strcpy(image, "O-O-O");
  29.      return;
  30.    }
  31.    int k = 0;
  32.  
  33.    if (p.Type() == Piece::Pawn)
  34.    {
  35.       if (emove.Capture().IsEmpty())
  36.       {
  37.      image[k] = m.DestSquare().FileImage();
  38.      k++;
  39.      image[k] = m.DestSquare().RankImage();
  40.      k++;
  41.       }
  42.       else
  43.       {
  44.      image[k] = m.StartSquare().FileImage();
  45.      k++;
  46.      image[k] = 'x';
  47.      k++;
  48.      image[k] = m.DestSquare().FileImage();
  49.      k++;
  50.      image[k] = m.DestSquare().RankImage();
  51.      k++;
  52.       }
  53.       if (emove.Special() == ExtendedMove::Promotion)
  54.       {
  55.      image[k] = '=';
  56.      k++;
  57.          image[k] = Piece::Image(m.PromoteTo());
  58.      k++;
  59.       }
  60.       image[k] = '\0';
  61.       return;
  62.    } 
  63.    else
  64.    {
  65.       image[k] = Piece::Image(p.Type());
  66.       k++;
  67.       Square squares[Bearing::MaxBearSq];
  68.       unsigned n = Bearing::Attack(b, m.DestSquare(), b.Side(), squares);
  69.       int dups = 0;
  70.       int files[8];
  71.       int ranks[8];
  72.  
  73.       if (n > 1)
  74.       {
  75.      for (unsigned i = 0; i < n; i++)
  76.      {
  77.         if (b[squares[i]].Type() == p.Type())
  78.         {
  79.            files[dups] = squares[i].File();
  80.            ranks[dups] = squares[i].Rank(White);
  81.            ++dups;
  82.         }
  83.      }
  84.       }
  85.       if (dups > 1)
  86.       {
  87.      // need to disambiguate move.  There are some rare cases
  88.      // (e.g. a player with 3 rooks) for which this code might
  89.      // not be sufficient.
  90.      if (files[0] != files[1])
  91.      {
  92.         image[k] = m.StartSquare().FileImage();
  93.         k++;
  94.      }
  95.          else
  96.      {
  97.         image[k] = m.StartSquare().RankImage();
  98.         k++;
  99.      }
  100.       }
  101.       if (!emove.Capture().IsEmpty())
  102.       {
  103.      image[k] = 'x';
  104.      k++;
  105.       }
  106.       image[k] = m.DestSquare().FileImage();
  107.       k++;
  108.       image[k] = m.DestSquare().RankImage();
  109.       k++;
  110.       image[k] = '\0';
  111.    }
  112. }
  113.  
  114. Move Notation::
  115. Value(const Board & board,
  116.       const ColorType side, char *image)
  117. {
  118.    char *p;
  119.    int rank = 0;
  120.    int file = 0;
  121.  
  122.    Piece::PieceType piece;
  123.    Piece:: PieceType promotion = Piece::Invalid;
  124.    Square dest, start;
  125.    Boolean capture = False;
  126.  
  127.    for (p = image; isspace(*p); ++p);
  128.    if (!isalpha(*p))
  129.       return Move::NullMove();
  130.    if (toupper(*p) == 'O')
  131.    {
  132.       // castling, we presume
  133.       char tmp[10];
  134.  
  135.       strncpy(tmp, p, 9);
  136.       for (char *q = tmp; *q; q++)
  137.      *q = toupper(*q);
  138.       return Move::Value(tmp, side);
  139.    }
  140.    if (isupper(*p))
  141.    {
  142.       piece = Piece::Value(*p);
  143.       ++p;
  144.    }
  145.    else
  146.    {
  147.       piece = Piece::Pawn;
  148.       file = *p - 'a' + 1;
  149.       if (*(p + 1) == 'x')
  150.       {
  151.      capture = True;
  152.      ++p;
  153.       }
  154.    }
  155.    if (piece == Piece::Invalid)
  156.       return Move::NullMove();
  157.    if (piece != Piece::Pawn)
  158.    {
  159.       // look for disambiguating rank or file, e.g. 'b' in "Nbd7".
  160.       if (isdigit(*p))
  161.       {
  162.      rank = *p - '0';
  163.      ++p;
  164.       }
  165.       else if (*p != 'x' && isalpha(*p) && isalpha(*(p + 1)))
  166.       {
  167.      file = *p - 'a' + 1;
  168.      ++p;
  169.       }
  170.    }
  171.    if (*p == 'x')
  172.    {
  173.       capture = True;
  174.       ++p;
  175.    }
  176.    // remainder of move should be a square identifier, e.g. "g7"
  177.    dest = Square::Value(p);
  178.    if (dest == Square::Invalid())
  179.       return Move::NullMove();
  180.    p += 2;
  181.    if (*p == '=')
  182.    {
  183.       promotion = Piece::Value(*(p + 1));
  184.       if (piece != Piece:: Pawn || promotion == Piece::Invalid)
  185.          return Move::NullMove();
  186.    }
  187.    // ok, now we need to figure out where the start square is.
  188.  
  189.    int dups = 0;
  190.  
  191.    if (capture && piece == Piece::Pawn && board[dest].IsEmpty() &&
  192.        dest.Rank(board.Side()) != 8)
  193.    {
  194.       // en passant capture, special case
  195.       int start_rank = (board.Side() == White) ?
  196.       dest.Rank(White) - 1 :
  197.       dest.Rank(White) + 1;
  198.  
  199.       start = Square(file, start_rank, White);
  200.       dups = 1;
  201.    }
  202.    else
  203.    {
  204.       static Square squares[36];
  205.       int n = Bearing::Attack(board, dest, side, squares);
  206.  
  207.       for (int i = 0; i < n; i++)
  208.       {
  209.      Square maybe(squares[i]);
  210.  
  211.      if (board[maybe].Type() == piece)
  212.      {
  213.         if (file && maybe.File() != file)
  214.            continue;
  215.         else if (rank && maybe.Rank(White) != rank)
  216.            continue;
  217.         else
  218.         {
  219.                // Possible move to this square.  Make sure it is legal.
  220.            
  221.            Board board_copy(board);
  222.            ExtendedMove emove(board_copy,maybe,dest,promotion);
  223.            board_copy.MakeMove(emove);
  224.            if (board_copy.num_attacks(
  225.               board_copy.KingPos(board_copy.OppositeSide()),
  226.           board_copy.Side()) == 0)
  227.                {               
  228.               ++dups;
  229.               start = maybe;
  230.                }
  231.         }
  232.      }
  233.       }
  234.    }
  235.    if (dups == 1)
  236.       return Move(start, dest, promotion);
  237.    else                // ambiguous move
  238.       return Move::NullMove();
  239. }
  240.